package com.oazon.moco.serialport.core;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidParameterException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import com.oazon.common.Logger;
import com.oazon.common.util.Utils;

import android.os.Handler;
import android.os.Message;
import android_serialport_api.SerialPort;

public class Serial {

	public static final String TAG = "SerialRT";
	public static final String TAG_THREAD = "SerialThread";
	protected static SerialPort mSerialPort;
	protected OutputStream mOutputStream;
	private InputStream mInputStream;
	Handler handler;
	ReceiveThread mReceiveThread = new ReceiveThread();
	SendingThread mSendingThread = new SendingThread();
	HandleThread handleThread = new HandleThread();

	boolean isrunning = false;
	Queue<Pack> sendqueue = new ConcurrentLinkedQueue<Pack>();
	Queue<Pack> readqueue = new ConcurrentLinkedQueue<Pack>();

	public static Serial serial;

	public Serial() {
		try {
			mSerialPort = new SerialPort(new File("/dev/ttyS2"), 115200, 0);
			mOutputStream = mSerialPort.getOutputStream();
			mInputStream = mSerialPort.getInputStream();
		} catch (InvalidParameterException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (UnsatisfiedLinkError e) {
			e.printStackTrace();
		}catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * 这个方法是设置端口的
	 */
	public void setSerialPort(String dev, int port) {
		try {
			mSerialPort = new SerialPort(new File(dev), port, 0);
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static Serial getInstance() {
		if (serial == null) {
			serial = new Serial();
		}
		return serial;
	}

	public void setHandler(Handler handler) {
		this.handler = handler;
	}

	/**
	 * 开启串口相关的工作线程
	 */
	public void start() {

		isrunning = true;
		if (mSerialPort != null) {

			if (!mSendingThread.isAlive()) {
				mSendingThread.start();
			}
			if (!mReceiveThread.isAlive()) {
				mReceiveThread.start();
			}
			if (!handleThread.isAlive()) {
				handleThread.start();
			}
		}
	}

	/**
	 * 关闭串口相关的工作线程
	 */
	public void stop() {

		isrunning = false;
		if (mSendingThread != null) {
			try {
				mSendingThread.join(500);
				mSendingThread.interrupt();
				mSendingThread = null;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		if (mReceiveThread != null) {
			try {
				mReceiveThread.join(500);
				mReceiveThread.interrupt();
				mReceiveThread = null;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		if (handleThread != null) {
			try {
				handleThread.join(500);
				handleThread.interrupt();
				handleThread = null;
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

	private class ReceiveThread extends Thread {
		Pack p = null;

		@Override
		public void run() {
			super.run();
			Logger.d(TAG_THREAD, "receive thread is running");
			while (isrunning) {
				try {
					if (mInputStream == null) {
						Logger.e(TAG, "串口未初始化！");
						throw new NoInput("串口未初始化！");
					}
					p = new Pack();
					p = p.getPack(mInputStream);
					readqueue.add(p);
					Logger.d(TAG, "received:"+Utils.toHex(p.tobytes(),','));
				} catch (IOException e) {
					Logger.d(TAG, "IOException");
					e.printStackTrace();
				} catch (NoInput e) {
					Logger.d(TAG, "NoInput");
					e.printStackTrace();
				} catch (BadPackageException e) {
					Logger.d(TAG, "BadPackageException");
					e.printStackTrace();
				}
			}
			Logger.d(TAG_THREAD, "receive thread is end");
		}
	}

	static int i = 0;

	// int是十六进制的数
	public void send(Pack p) {

		if (p.getType() == (byte) 0x00) {
			sendqueue.add(p);
		} else {
			sendqueue.add(p);

		}
	}

	public void answer(byte result, int number) {
		Pack p = new Pack();
		p.setType(Type.SM_ANSWER);
		p.setData(new byte[] { result });
		send(p);
	}

	public class SendingThread extends Thread {
		@Override
		public void run() {
			Logger.d(TAG_THREAD, "send thread is running");
			while (isrunning) {
				try {

					Pack p = sendqueue.poll();
					if (p == null) {
						try {
							Thread.sleep(10);
							continue;
						} catch (InterruptedException e) {

						}
					}
					if (mOutputStream != null) {
						mOutputStream.write(p.tobytes());
						Logger.d(TAG, "sended:"+Utils.toHex(p.tobytes(),','));
					} else {
						return;
					}
				} catch (IOException e) {
					e.printStackTrace();
					return;
				}
			}
			Logger.d(TAG_THREAD, "send thread is end");
		}

	}

	public class HandleThread extends Thread {

		public void run() {
			super.run();
			Logger.d(TAG_THREAD, "handle thread is running");
			while (isrunning) {
				Pack p = readqueue.poll();
				if (p == null) {
					try {
						Thread.sleep(50);
						continue;
					} catch (InterruptedException e) {
					}
				} else {

					Message message = new Message();
					message.what = 1;
					message.obj = p;
//					if(p.getType() == SerialHandlerService.M_VOLUM_UP ||p.getType() == SerialHandlerService.M_VOLUM_DOWN){
//						handler.removeMessages(1);
//						handler.sendMessageDelayed(message, 90);
//					}else{
					if(handler != null)
						handler.sendMessage(message);	
//					}

				}
			}
			Logger.d(TAG_THREAD, "handle thread is end");
		}
	}

	public void closeSerialPort() {
		if (mSerialPort != null) {
			mSerialPort.close();
			mSerialPort = null;
		}

	}
}
